{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Transformers 설치 방법\n",
    "! pip install transformers datasets evaluate accelerate\n",
    "# 마지막 릴리스 대신 소스에서 설치하려면, 위 명령을 주석으로 바꾸고 아래 명령을 해제하세요.\n",
    "# ! pip install git+https://github.com/huggingface/transformers.git"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Image-to-Image 작업 가이드 [[image-to-image-task-guide]]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Image-to-Image 작업은 애플리케이션이 이미지를 입력받아 또 다른 이미지를 출력하는 작업입니다. 여기에는 이미지 향상(초고해상도, 저조도 향상, 빗줄기 제거 등), 이미지 복원 등 다양한 하위 작업이 포함됩니다.\n",
    "\n",
    "이 가이드에서는 다음을 수행하는 방법을 보여줍니다.\n",
    "- 초고해상도 작업을 위한 image-to-image 파이프라인 사용,\n",
    "- 파이프라인 없이 동일한 작업을 위한 image-to-image 모델 실행\n",
    "\n",
    "이 가이드가 발표된 시점에서는, `image-to-image` 파이프라인은 초고해상도 작업만 지원한다는 점을 유의하세요.\n",
    "\n",
    "필요한 라이브러리를 설치하는 것부터 시작하겠습니다.\n",
    "\n",
    "```bash\n",
    "pip install transformers\n",
    "```\n",
    "\n",
    "이제 [Swin2SR 모델](https://huggingface.co/caidas/swin2SR-lightweight-x2-64)을 사용하여 파이프라인을 초기화할 수 있습니다. 그런 다음 이미지와 함께 호출하여 파이프라인으로 추론할 수 있습니다. 현재 이 파이프라인에서는 [Swin2SR 모델](https://huggingface.co/caidas/swin2SR-lightweight-x2-64)만 지원됩니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from transformers import pipeline\n",
    "\n",
    "device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n",
    "pipe = pipeline(task=\"image-to-image\", model=\"caidas/swin2SR-lightweight-x2-64\", device=device)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "이제 이미지를 불러와 봅시다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from PIL import Image\n",
    "import requests\n",
    "\n",
    "url = \"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/cat.jpg\"\n",
    "image = Image.open(requests.get(url, stream=True).raw)\n",
    "\n",
    "print(image.size)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```bash\n",
    "# (532, 432)\n",
    "```\n",
    "<div class=\"flex justify-center\">\n",
    "     <img src=\"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/cat.jpg\" alt=\"Photo of a cat\"/>\n",
    "</div>\n",
    "\n",
    "이제 파이프라인으로 추론을 수행할 수 있습니다. 고양이 이미지의 업스케일된 버전을 얻을 수 있습니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "upscaled = pipe(image)\n",
    "print(upscaled.size)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```bash\n",
    "# (1072, 880)\n",
    "```\n",
    "\n",
    "파이프라인 없이 직접 추론을 수행하려면 Transformers의 `Swin2SRForImageSuperResolution` 및 `Swin2SRImageProcessor` 클래스를 사용할 수 있습니다. 이를 위해 동일한 모델 체크포인트를 사용합니다. 모델과 프로세서를 초기화해 보겠습니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from transformers import Swin2SRForImageSuperResolution, Swin2SRImageProcessor \n",
    "\n",
    "model = Swin2SRForImageSuperResolution.from_pretrained(\"caidas/swin2SR-lightweight-x2-64\").to(device)\n",
    "processor = Swin2SRImageProcessor(\"caidas/swin2SR-lightweight-x2-64\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`pipeline` 우리가 직접 수행해야 하는 전처리와 후처리 단계를 추상화하므로, 이미지를 전처리해 보겠습니다. 이미지를 프로세서에 전달한 다음 픽셀값을 GPU로 이동시키겠습니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pixel_values = processor(image, return_tensors=\"pt\").pixel_values\n",
    "print(pixel_values.shape)\n",
    "\n",
    "pixel_values = pixel_values.to(device)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "이제 픽셀값을 모델에 전달하여 이미지를 추론할 수 있습니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "\n",
    "with torch.no_grad():\n",
    "  outputs = model(pixel_values)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "출력은 아래와 같은 `ImageSuperResolutionOutput` 유형의 객체입니다 👇 \n",
    "\n",
    "```\n",
    "(loss=None, reconstruction=tensor([[[[0.8270, 0.8269, 0.8275,  ..., 0.7463, 0.7446, 0.7453],\n",
    "          [0.8287, 0.8278, 0.8283,  ..., 0.7451, 0.7448, 0.7457],\n",
    "          [0.8280, 0.8273, 0.8269,  ..., 0.7447, 0.7446, 0.7452],\n",
    "          ...,\n",
    "          [0.5923, 0.5933, 0.5924,  ..., 0.0697, 0.0695, 0.0706],\n",
    "          [0.5926, 0.5932, 0.5926,  ..., 0.0673, 0.0687, 0.0705],\n",
    "          [0.5927, 0.5914, 0.5922,  ..., 0.0664, 0.0694, 0.0718]]]],\n",
    "       device='cuda:0'), hidden_states=None, attentions=None)\n",
    "```\n",
    "`reconstruction`를 가져와 시각화를 위해 후처리해야 합니다. 어떻게 생겼는지 살펴봅시다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "outputs.reconstruction.data.shape\n",
    "# torch.Size([1, 3, 880, 1072])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "출력 텐서의 차원을 축소하고 0번째 축을 제거한 다음, 값을 클리핑하고 NumPy 부동소수점 배열로 변환해야 합니다. 그런 다음 [1072, 880] 모양을 갖도록 축을 재정렬하고 마지막으로 출력을 0과 255 사이의 값을 갖도록 되돌립니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "# 크기를 줄이고, CPU로 이동하고, 값을 클리핑\n",
    "output = outputs.reconstruction.data.squeeze().cpu().clamp_(0, 1).numpy()\n",
    "# 축을 재정렬\n",
    "output = np.moveaxis(output, source=0, destination=-1)\n",
    "# 값을 픽셀값 범위로 되돌리기\n",
    "output = (output * 255.0).round().astype(np.uint8)\n",
    "Image.fromarray(output)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"flex justify-center\">\n",
    "     <img src=\"https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/cat_upscaled.png\" alt=\"Upscaled photo of a cat\"/>\n",
    "</div>"
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 4
}
